package com.abso.mp3tunes.locker.ui.jobs;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;

import com.abso.mp3tunes.locker.core.LockerServiceException;
import com.abso.mp3tunes.locker.ui.viewers.PendingNode;

/**
 * An abstract base class for jobs able to set tree viewer root nodes.
 */
public abstract class GetTreeRootNodesJob extends Job {

	/** The tree viewer being updated. */
	private TreeViewer viewer;

	/**
	 * Constructs a new job.
	 * 
	 * @param jobName
	 *            the job name.
	 * @param viewer
	 *            the tree viewer.
	 */
	public GetTreeRootNodesJob(String jobName, TreeViewer viewer) {
		this(jobName, "Loading...", viewer);
	}

	/**
	 * Constructs a new job.
	 * 
	 * @param jobName
	 *            the job name.
	 * @param pendingNodeName
	 *            the temporary text used as label during the computation.
	 * @param viewer
	 *            the tree viewer.
	 */
	public GetTreeRootNodesJob(String jobName, String pendingNodeName,
			TreeViewer viewer) {
		super(jobName);
		this.viewer = viewer;
		viewer.setInput(new Object[] { new PendingNode(pendingNodeName) });
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor)
	 */
	protected IStatus run(IProgressMonitor monitor) {
		Object[] rootNodes = null;
		try {
			rootNodes = doGetRootNodes();
		} catch (LockerServiceException e) {
			rootNodes = new Object[] { e };
		}
		setInputInUIThread(rootNodes);
		return Status.OK_STATUS;
	}

	/**
	 * Computes and returns the root nodes.
	 * 
	 * @return the root nodes.
	 * @throws LockerServiceException
	 *             if an error occurred computing the root nodes.
	 */
	protected abstract Object[] doGetRootNodes() throws LockerServiceException;

	/**
	 * Refreshes the tree viewer by setting its input.
	 * 
	 * @param rootNodes
	 *            the root nodes.
	 */
	private void setInputInUIThread(final Object[] rootNodes) {
		Control control = viewer.getControl();
		if ((control != null) && !control.isDisposed()) {
			Display display = control.getDisplay();
			if (display != null) {
				display.asyncExec(new Runnable() {
					public void run() {
						viewer.setInput(rootNodes);
					}
				});
			}
		}
	}

}
